# external imports
import web
from web import form

# Owl imports
import validate
import model
import webutil
import config

import time

#A_DO 65 refactor to NEW / EDIT / DELETE

from model import User
from model import commit

web.config.debug = config.DEBUG
render_old = web.template.render('webpages/')
render = web.template.render('webpages/', base='layout')


urls = ('/welcome', 'welcome',
        '/login', 'login',
        '^/user/([\w][\w]*)/groups/edit$', 'user_groups_edit',
        '^/user/([\w][\w]*)/edit$', 'user_edit',
        '^/user/([\w][\w]*)/groups$', 'user_groups',
        '/user/add', 'user_add',
        '^/user/([\w][\w]*)', 'user_read'
        )
app = web.application(urls, globals())

#===============================================================================
# Sessions
#===============================================================================
# Normal production sessions

# session = web.session.Session(app, web.session.DiskStore('sessions'), initializer={'authentic':0})

if config.DEBUG == True:
    # sessions necessary when debug set to true
    if web.config.get('_session') is None:
        session = web.session.Session(app, web.session.DiskStore('sessions'), {'name': ''})
        web.config._session = session
    else:
        session = web.config._session
else:
    session = web.session.Session(app, web.session.DiskStore('sessions'), initializer={'authentic':0})






#===============================================================================
# Form definitions
#===============================================================================
#UserForm = form.Form(
#    form.Textbox("name",
#        form.notnull,
#        form.Validator("This name failed validation. Please try another", lambda y: validate.name(y)[0]),
#        class_='inputtext write'),
#    form.Textbox("email",
#        form.notnull,
#        form.Validator("This is not a valid email", lambda y: validate.do(y, 'Email()')[0]),
#        class_='inputtext write'),
#
#    form.Password("password",
#        form.notnull,
#        form.Validator('Password must be more than 5', lambda x:len(x) > 5),
#        class_='inputtext write')  
#    )



def f_user_edit(u, render=True):
    '''Returns form html or object if "render" is set to false'''
    f = form.Form(
        form.Textbox("name",
            form.notnull,
            form.Validator("This name failed validation. Please try another", lambda y: validate.name(y)[0]),
            value=u.name,
            class_='inputtext write'),
        form.Textbox("email",
            form.notnull,
            form.Validator("This is not a valid email", lambda y: validate.do(y, 'Email()')[0]),
            value=u.email,
            class_='inputtext write'),
        form.Checkbox('active',
            value=u.active),
        form.Textbox("id", form.notnull,
            readonly=True,
            value=u.id, class_='inputtext readonly')  
            )
    if render:
        return f.render()
    else:
        return f
    
def f_user_insert(u, render=True):
    '''Create form for adding a user. Form Returns form html or object if "render" is set to false'''
    f = form.Form(
        form.Textbox("name",
            form.notnull,
            form.Validator("This name failed validation. Please try another", lambda y: validate.name(y)[0]),
            value=u.name,
            class_='inputtext write'),
        form.Textbox("email",
            form.notnull,
            form.Validator("This is not a valid email", lambda y: validate.do(y, 'Email()')[0]),
            value=u.email,
            class_='inputtext write'),
        form.Password("password",
            form.notnull,
            form.Validator('Password must be more than 5', lambda x:len(x) > 5),
            class_='inputtext write')  
            )
    if render:
        return f.render()
    else:
        return f

def user_form_locked(u, render=True):
    if u.active:
        active = 'True'
        active_class = 'inputtext readonly'
    else:
        active = 'False'
        active_class = 'inputtext inactive'
    f = form.Form(
        form.Textbox("name",
            form.notnull,
            form.Validator("This name failed validation. Please try another", lambda y: validate.name(y)[0]),
            value=u.name,
            readonly=True,
            class_='inputtext readonly'),
        form.Textbox("email",
            form.notnull,
            form.Validator("This is not a valid email", lambda y: validate.do(y, 'Email()')[0]),
            value=u.email,
            readonly=True,
            class_='inputtext readonly'),
        form.Textbox('active',
            value=active,
            readonly=True,
            class_=active_class),
        form.Textbox("id", form.notnull, readonly=True, value=u.id,
            class_='inputtext readonly')  
            )
    if render:
        return f.render()
    else:
        return f

def login_form():
        f = form.Form(
        form.Textbox("email",
            form.notnull,
            form.Validator("This is not a valid email", lambda y: validate.do(y, 'Email()')[0]),
            class_='inputtext write'),
        form.Password("password", form.notnull,
            form.Validator('Password must be more than 5 characters', lambda x:len(x) > 5),          
            class_='inputtext write')  
            )
        return f


class user_add: 
    def GET(self): 
        p = webutil.Page(web.ctx)
        u = User()
        p.form = f_user_insert(u)
        p.noun = 'user'
        p.verb = 'add'
        p.editable = True
        p.cache = True
        p.update()        
        return render.t_default(p)


    def POST(self):
        u = User() 
        form = f_user_insert(u, False) 
        p = webutil.Page(web.ctx)
        p.verb, p.noun = 'new', 'add'
        p.editable = True        
        if not form.validates():
            #Client side error 
            p.message = "Please check the values you have entered"           
        else:
            u = User(form.d.name)
            u.email = form.d.email
            u.password_hash = u.hash(form.d.password)
            u.save()
            form.valid, message = commit()
            if form.valid:
                #Success!
                raise web.seeother('/user/{0}'.format(form.d.name))
            else:
                #Server side error
                p.message = message
        p.update()  
        p.form = form.render()      
        return render.t_default(p)

     
class user_read: 
    def GET(self, user_name=None):
        p = webutil.Page(web.ctx) 
        model.commit()
        if not validate.not_number(user_name):
            user_name = int(user_name)
        u = User(user_name).read()       
        if u:
            groups = u.groups()
            # build data set for table showing groups belonged to
            data = []
            for g in groups:
                data.append([g.id, g.name])            
            table = webutil.Table(data,['id', 'name'],'Groups this user belongs to','100%')
            p.table = table.render()
            p.form = user_form_locked(u)
            p.verb = 'view'
            p.noun = u.name
            p.update()
        else:
            p.message = "User not found"
            p.name = "Page not found"
        return render.t_default(p)
    
class user_edit: 
    def GET(self, user_name=None):
        model.commit()
        p = webutil.Page(web.ctx)
        p.verb = 'edit' 
        u = User(user_name).read()
        if not u:
            p.message = 'User {0} does not exist'.format(user_name)
            p.noun = "Not found"
        else:
            p.form = f_user_edit(u)
            p.noun = u.name            
            p.editable = True   
        p.update()
        return render.t_default(p)

    def POST(self, user_name=None):
        u = User(user_name)
        # u = u.read() 
        print 10 * '---'
        print 10, u
        print 11, u.password_hash
        form = f_user_edit(u, False) 
        p = webutil.Page(web.ctx)
        # p.verb, p.noun = 'new', 'add'
        p.editable = True        
        if not form.validates():
            #Client side error 
            p.message = "Please check the values you have entered"           
        else:
            u = User(form.d.name)
            u = u.read()
            u.email = form.d.email
            u.active = form.d.active
            # u.password_hash = u.hash(form.d.password)
            u.save()
            form.valid, message = commit()
            if form.valid:
                #Success!
                raise web.seeother('/user/{0}'.format(form.d.name))
            else:
                #Server side error
                p.message = message
        p.update()  
        p.form = form.render()      
        return render.t_default(p)
    
class user_groups:

    def GET(self, user_name=None):
        p = webutil.Page(web.ctx) 
        model.commit()
        if not validate.not_number(user_name):
            user_name = int(user_name)
        u = User(user_name).read()       
        if u:
            groups = u.groups()
            # build data set for table showing groups belonged to
            data = []
            for g in groups:
                data.append([g.id, g.name])            
            table = webutil.Table(data,['id', 'name'],'Groups this user belongs to','100%', 'Edit')
            p.table = table.render()
            # p.form = user_form_locked(u)
            p.form = False
            p.verb = 'view groups'
            p.noun = u.name
            p.update()
        else:
            p.message = "User not found"
            p.name = "Page not found"
        return render.t_default(p)
    
class user_groups_edit:

    def GET(self, user_name=None):
        print 10 * '---'
        print 'get' 
        p = webutil.Page(web.ctx)
        p.editable_table = True 
        model.commit()
        if not validate.not_number(user_name):
            user_name = int(user_name)
        u = User(user_name).read()       
        if u:
            groups = u.groups()
            # build data set for table showing groups belonged to
            data = []
            for g in groups:
                checkbox = '<input type="checkbox" name={0} value="" checked="yes"/>'.format(g.id)
                data.append([g.id, g.name, checkbox])            
            table = webutil.Table(data,['id', 'name', 'active'],'Groups this user belongs to','100%', None, True)
            p.table = table.render()
            # p.form = user_form_locked(u)
            p.form = False
            p.verb = 'edit groups'
            p.noun = u.name
            p.update()
        else:
            p.message = "User not found"
            p.name = "Page not found"
        return render.t_default(p)
    

    def POST(self, user):
        print 10 * '---'      
        data = web.input() 
        print data
        print "10 fred"
        return "20 fred"
        u = User()
        # Set up page variables
        u = User(user).read()
        
        raise web.seeother('http://www.google.com')
        # raise web.seeother('/user/{0}/groups'.format(user))
        
        
        
#A_DO: 14 add Change password function

    
class login: 
    def GET(self):
#        model.commit()
#        u = User(user_name).read()
#        if not u:
#            # u = User()
#            n = webutil.NotFound(web.ctx)
#            n.message = 'User {0} does not exist'.format(user_name)
#            return render.t_notfound(n)
        f = webutil.Found(web.ctx)
#        u.path = f.path
#        u.message = None
        ret_form = login_form()
        ret_form.path = f.path
        ret_form.noun = ''
        ret_form.verb = 'login'
        ret_form.message = None
        ret_form.no_cache = False
#        ret_form.d.name = 'login'
        ret_form.title = 'login'
        ret_form.editable = False
        ret_form.login = True
        ret_form.table = False
        return render.t_form(ret_form)
    
    def POST(self):
        form = login_form() 
        form.message = ''
        f = webutil.Found(web.ctx)
        form.path = f.path
        form.verb = 'login'
        form.noun = ''
        form.name = 'Login User'
        form.title = 'Login User'
        form.no_cache = True
        if not form.validates(): 
            # return render.formSimple(form)
            form.editable = False
            form.login = True
            form.message = "Please check the values you have entered"
            return render.t_form(form)
        else:
            u = User()
            u.email = form.d.email
            print 101, u.email
            n = u.read_email()
            print 202, n
            if n.authenticates(form.d.password):
                print 333, session
                session.authentic = 1
                session.email = n.email
                session.name = n.name
                print 444, session
                # session.save()
                # raise web.seeother('/user/welcome/{0}'.format(n.name))
                raise web.seeother('/welcome')
                #return session.name
            else:
                form.message = 'Login failed'   
                form.login = True
                form.editable = False    
                return render.t_form(form)
class welcome: 
    def GET(self): 
        n = webutil.Found(web.ctx)
        # print 555, session
        # p = z
        n.name = 'rrrrr'
        n.message = 'Hello to :' + session.name
        return render.t_notfound(n) 
       


if __name__ == "__main__":
    # switched off for sessions?
    if config.DEBUG: web.internalerror = web.debugerror 
    app.run()
    
#    print session
#    session.school = 'collis'
#    print session
#    print dir(session.store)

#TEST: get User not found page